{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from abc import abstractmethod\n",
    "from ast import Index\n",
    "from operator import index\n",
    "from os import makedirs, name, path, remove\n",
    "from typing import List, Tuple\n",
    "import numpy as np\n",
    "from numpy.lib import index_tricks\n",
    "from numpy.lib.function_base import disp, percentile\n",
    "import pandas as pd\n",
    "from pandas.core.accessor import DirNamesMixin\n",
    "from collections import Counter\n",
    "from numpy.core.numeric import outer\n",
    "import os\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## step 0 配置文件\n",
    "\n",
    "import os\n",
    "import pandas as pd\n",
    "\n",
    "# 设置工作路径\n",
    "pathWork = r'D:\\\\workspace\\\\张3\\\\IrPdPtRhRu-团簇处理数据'\n",
    "\n",
    "# 设置文件名\n",
    "excelFileName = '1473k-30-30-30.xlsx'\n",
    "\n",
    "# 构建完整的文件路径\n",
    "fullFilePath = os.path.join(pathWork, excelFileName)\n",
    "\n",
    "# 尝试读取Excel文件\n",
    "try:\n",
    "    data = pd.read_excel(fullFilePath)\n",
    "    print(\"文件读取成功！\")\n",
    "except FileNotFoundError:\n",
    "    print(f\"文件未找到: {fullFilePath}\")\n",
    "\n",
    "# 如果需要，可以打印出文件路径进行检查\n",
    "print(\"完整的文件路径:\", fullFilePath)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "## 计算元素 Al Co Cr Fe Ni\n",
    "atomList = ['Ir' ,'Pd' ,'Pt' ,'Rh','Ru' ]\n",
    "\n",
    "## 原子距离\n",
    "nearNumber = 3    #截断值要求大于第一近邻小于第二近邻, FCC:(3.8*0.7) = 2.6 < d < 3.8, BCC:(3.5*0.86) = 3 < d < 3.5\n",
    "\n",
    "## 输入占位数\n",
    "# atomSeriesNumbers = [4,5,6,7,8,9,10] 若最后一步没有结果，尝试将此处配位数降低\n",
    "atomSeriesNumbers = [3,4,5,6,7,8,9,10,11,12]\n",
    "\n",
    "## 创建工作文件夹\n",
    "def mkdir( path):\n",
    "    # path = path.strip()\n",
    "    # path = path.restrip(\"\\\\\")\n",
    "\n",
    "    isExists = os.path.exists(path)\n",
    "\n",
    "    if not isExists:\n",
    "        os.makedirs(path)\n",
    "    else:\n",
    "        pass\n",
    "\n",
    "\n",
    "## datasets 输出文件路径\n",
    "dataSets = f'{pathWork}\\datasets'\n",
    "\n",
    "## 输出原子距离文件路径\n",
    "AtomDistance = f'{pathWork}\\AtomDistance-1nn'\n",
    "\n",
    "## 输出原子占位数文件路径\n",
    "AtomDistanceSort = f'{pathWork}\\{excelFileName}-AtomDistanceSort-1nn'\n",
    "\n",
    "mkdir(dataSets)\n",
    "makedirs(AtomDistance)\n",
    "mkdir(AtomDistanceSort)\n",
    "\n",
    "\n",
    "## Step 1  切分原子文件 ##\n",
    "\n",
    "# 循环切割出每个原子的坐标文件\n",
    "for ele in atomList:\n",
    "\n",
    "    ## 读取数据\n",
    "    fileOutName = f'{ele}Data.xlsx'\n",
    "    pathOut = os.path.join(dataSets,fileOutName)\n",
    "\n",
    "    ## 按原子类别切割\n",
    "    df =  data.loc[data.iloc[:,-1].str.find(ele) == 1]\n",
    "    df.to_excel(pathOut)\n",
    "\n",
    "    print('step1 '  + ele +' over')\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "## Step 2  计算原子距离  ##\n",
    "def atomDis(atom, dataSets, AtomDistance, nearNumber):\n",
    "    # 读取数据\n",
    "    fileReadName = f'{atom}Data.xlsx'\n",
    "    fileOutName = f'{atom}{atom}-Distance-1nn.xlsx'\n",
    "    pathIn = os.path.join(dataSets, fileReadName)\n",
    "    pathOut = os.path.join(AtomDistance, fileOutName)\n",
    "    \n",
    "    # 读取数据\n",
    "    df1 = pd.read_excel(pathIn)\n",
    "    df3 = df1.loc[:, 'x':'z']\n",
    "    \n",
    "    # 转变成数组\n",
    "    arrayA = df3.to_numpy()\n",
    "    lenA = len(arrayA)\n",
    "    \n",
    "    outcomeArr = []\n",
    "    k = 0  # 计数器\n",
    "    for i in range(lenA):\n",
    "        k=k+1\n",
    "        print(k)\n",
    "        for j in range(i+1):\n",
    "            dis = np.linalg.norm(arrayA[i]-arrayA[j])*105  #POSCAR中第二行查看晶格常数\n",
    "            if i == j:\n",
    "                pass\n",
    "            else:\n",
    "                if dis <= nearNumber: ## 原子距离判定条件\n",
    "                    outcomeArr.append([arrayA[i][0],arrayA[i][1],arrayA[i][2],'#',(i+1),arrayA[j][0],arrayA[j][1],arrayA[j][2],'#',(j+1),dis])\n",
    "                else:\n",
    "                    pass\n",
    "    # 检查是否有数据可以创建DataFrame\n",
    "    if outcomeArr:\n",
    "        df2 = pd.DataFrame(outcomeArr)\n",
    "        df2.columns = [f'{atom}1_x', f'{atom}1_y', f'{atom}1_z', '#', f'{atom}1', f'{atom}2_x', f'{atom}2_y', f'{atom}2_z', '#', f'{atom}2', 'Distance']\n",
    "        df2.sort_values(by='Distance', inplace=True)  # 按距原子离排序\n",
    "        # 输出文件\n",
    "        df2.to_excel(pathOut, index=False)\n",
    "    else:\n",
    "        print(f\"No data to create DataFrame for atom: {atom}\")\n",
    "\n",
    "# 循环计算同类原子之间的距离\n",
    "for i in atomList:\n",
    "    atomDis(i, dataSets, AtomDistance, nearNumber)\n",
    "    print('step2 ' + str(i) + ' over')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "## 计算元素 Al Co Cr Fe Ni\n",
    "atomList = ['Co' ,'Fe' ,'Mn' ]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "## Step 3  计算原子配位数  ##\n",
    "\n",
    "\n",
    "def atomDisSort(atom,atomSeriesNumbers,AtomDistance,AtomDistanceSort):\n",
    "    \n",
    "    ## 读取数据\n",
    "    fileReadName = f'{atom}{atom}-Distance-1nn.xlsx'\n",
    "    fileOutName = f'{atom}{atom}-SeriesNumbers-1nn-{atomSeriesNumbers}.csv'\n",
    "    pathIn = os.path.join(AtomDistance,fileReadName)\n",
    "    pathOut = os.path.join(AtomDistanceSort,fileOutName)\n",
    " \n",
    "    df = pd.read_excel(pathIn)\n",
    "    #df2 = df.iloc[:,5:6] \n",
    "    df2 = df.iloc[:,4:5]\n",
    "\n",
    "    ## 转变成数组\n",
    "    arrayA = df2.to_numpy()\n",
    "\n",
    "    ## 转变为列表\n",
    "    lst = []\n",
    "    for i in arrayA:\n",
    "        lst.append(int(i))\n",
    "\n",
    "    ## 计算每个原子出现的个数，将原子序号和出现个数存入字典\n",
    "    b = dict(Counter(lst))\n",
    "\n",
    "    ## 计算原子配位数（连续数）符合要求的\n",
    "    countdic = {key:value for key,value in b.items()if value == atomSeriesNumbers}\n",
    "\n",
    "    ## 输出符合要求的key值（原子序号），并用列表存储\n",
    "    outkeys = countdic.keys()\n",
    "    outkeys_lst = []\n",
    "    for i in outkeys:\n",
    "        outkeys_lst.append(i)\n",
    "\n",
    "    ## 判断列表是否为空\n",
    "    if outkeys_lst == []:\n",
    "        pass\n",
    "    else:\n",
    "        ## 用key值（原子序号）作为索引,回原始数据df中寻找符合要求的行，并添加到df5中\n",
    "        df5 = pd.DataFrame()\n",
    "        \n",
    "        for j in range(len(outkeys_lst)):\n",
    "            df4 = df.loc[df.loc[:,f'{atom}1'] == outkeys_lst[j]]\n",
    "            df5 = pd.concat([df5,df4],ignore_index=True)\n",
    "\n",
    "        # 输出文件\n",
    "        df5.to_csv(pathOut)\n",
    "\n",
    "\n",
    "# 遍历每个原子距离文件，找出符合指定配位数的原子对\n",
    "for i in atomList:\n",
    "    for j in atomSeriesNumbers:\n",
    "        atomDisSort(i,j,AtomDistance,AtomDistanceSort)\n",
    "        print('step 3 '+str(i)+'-'+str(j)+' over')\n",
    "\n",
    "\n",
    "print('计算完成')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.2"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
